package com.rednote.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rednote.common.Result;
import com.rednote.common.JwtUtil;
import com.rednote.common.UserContextHolder;
import com.rednote.entity.Posts;
import com.rednote.entity.dto.CommentDTO;
import com.rednote.entity.dto.PostDTO;
import com.rednote.entity.vo.PostCardVO;
import com.rednote.entity.vo.PostVO;
import com.rednote.service.CommentsService;
import com.rednote.service.PostsService;

import com.rednote.service.RecommendationService;
import com.rednote.service.UsersService;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.web.bind.annotation.*;

import jakarta.annotation.Resource;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import com.rednote.common.OssUtil;

import javax.imageio.ImageIO;

/**
 * 用户帖子表(Posts)控制层
 *
 * @author yao suxuan
 * @since 2025-05-24 18:10:30
 */
@RestController
@RequestMapping("/posts")
public class PostsController {
    @Resource
    private PostsService postsService;
    @Resource
    private CommentsService commentsService;
   @Resource
    private RecommendationService recommendationService;
    @Resource
    private JwtUtil jwtUtil;
    @Resource
    private UsersService usersService;
    @Resource
    private OssUtil ossUtil;

    /**
     * 分页查询
     *
     * @param page 页码
     * @param size 每页大小
     * @return 查询结果
     */
    @GetMapping
    public Page<Posts> list(@RequestParam(defaultValue = "1") Integer page, 
                                        @RequestParam(defaultValue = "10") Integer size) {
        return postsService.page(new Page<>(page, size));
    }

    /**
     * 用户对帖子评论
     *
     * @return 评论结果
     */
    @PostMapping("/comments")
    public Result<?> commentPost(@ModelAttribute CommentDTO commentDTO) {
        try {
            commentsService.createComment(commentDTO.getId(), commentDTO.getContent(),commentDTO.getImages(),true);
            return Result.success("评论成功");
        }
        catch (Exception e) {
            return Result.fail("评论失败: " + e.getMessage());
        }
    }

    /**
     * 获取帖子详情
     * @param id 帖子ID
     * @param page 页码
     * @param pageSize 每页大小
     * @return 帖子详情
     */
    @GetMapping("/detail")
    public Result<?> getPostDetail(@RequestParam Integer id,
                                                @RequestParam(defaultValue = "1") int page,
                                                @RequestParam(defaultValue = "10") int pageSize) {

        try {
            PostVO detail = postsService.getPostDetail(id,page,pageSize);
            return Result.success(detail);
        } catch (Exception e) {
            return Result.fail("查询失败: " + e.getMessage());
        }
    }

    /**
     * 获取推荐帖子列表
     *
     * @param page 页码
     * @param limit 每页大小
     * @return 推荐帖子列表
     */
    @GetMapping("/recommend")
    public Result<?> recommendPosts(@RequestParam(defaultValue = "1") int page,
                                    @RequestParam(defaultValue = "10") int limit) {
        try {
            int cursor = (page - 1) * limit;
            List<PostCardVO> list = postsService.recommend(cursor, limit);
            return Result.success(list);
        } catch (Exception e) {
            return Result.fail("推荐失败: " + e.getMessage());
        }
    }

    //推荐下5个相关视频
    @GetMapping("/recommendNext")
    public Result<?> recommendNextPosts(@RequestParam Integer postId,
                                        @RequestParam(defaultValue = "1") int page,
                                        @RequestParam(defaultValue = "5") int limit){
        try{
            Page<Integer>posts=recommendationService.getRelatedRecommendations( postId, page, limit);
            return Result.success(posts);
        } catch (Exception e) {
            return Result.fail("推荐失败: " + e.getMessage());
        }
    }

    /**
     * 获取我的帖子列表
     *
     * @param page 页码
     * @param size 每页大小
     * @return 查询结果
     */
    @GetMapping("/my")
    public Result<?> getMyPosts(@RequestParam(defaultValue = "1") Integer page,
                               @RequestParam(defaultValue = "10") Integer size) {
        try {
            Integer userId = UserContextHolder.getUserId();
            List<PostCardVO> postsPage = postsService.getMyPosts(userId, page, size);
            return Result.success(postsPage);
        } catch (Exception e) {
            return Result.fail("获取我的帖子失败: " + e.getMessage());
        }
    }

    /**
     * 获取某人帖子列表
     *
     * @param page 页码
     * @param size 每页大小
     * @return 查询结果
     */
    @GetMapping("/sb")
    public Result<?> getSbPosts(@RequestParam Integer userId,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size) {
        try {
            List<PostCardVO> postsPage = postsService.getMyPosts(userId, page, size);
            return Result.success(postsPage);
        } catch (Exception e) {
            return Result.fail("获取用户的帖子失败: " + e.getMessage());
        }
    }

    /**
     * 发布新帖子
     *
     * @param token 用户的JWT令牌
     * @param     postDTO 帖子数据传输对象，包含标题、内容、标签、视频和图片
     * @return           发布结果
     */
    @PostMapping("/publish")
    public Result<?> publishPost(@RequestHeader("Authorization") String token,
                                 @ModelAttribute PostDTO postDTO) {
        File tempFile = null;
        File coverFile = null;
        FFmpegFrameGrabber grabber = null;
        try {
            // Token 验证
            if (token == null || !token.startsWith("Bearer ")) {
                return Result.fail("未提供有效的token");
            }
            String actualToken = token.substring(7);
            if (!jwtUtil.validateToken(actualToken)) {
                return Result.fail("token无效或已过期");
            }
            var claims = jwtUtil.parseToken(actualToken);
            Integer userId = ((Number) claims.get("userId")).intValue();


            // 验证视频文件
            if (postDTO.getVideo() != null && !postDTO.getVideo().isEmpty()) {
                String videoContentType = postDTO.getVideo().getContentType();
                // 视频格式验证
                if (videoContentType == null || !videoContentType.startsWith("video/")) {
                    return Result.fail("不支持的视频格式");
                }
                // 视频大小限制：50MB
                long videoSize = postDTO.getVideo().getSize();
                if (videoSize > 50 * 1024 * 1024) {
                    return Result.fail("视频文件大小不能超过50MB");
                }
            }

            // 验证图片文件（仅当有图片时进行验证）
            if (postDTO.getImages() != null && !postDTO.getImages().isEmpty()) {
                for (MultipartFile image : postDTO.getImages()) {
                    String imageContentType = image.getContentType();
                    // 图片格式验证
                    if (imageContentType == null || !imageContentType.startsWith("image/")) {
                        return Result.fail("不支持的图片格式");
                    }
                    // 图片大小限制：10MB
                    if (image.getSize() > 10 * 1024 * 1024) {
                        return Result.fail("单个图片大小不能超过10MB");
                    }
                }
            }


            Posts post = new Posts();
            post.setUserId(userId);
            post.setTitle(postDTO.getTitle());
            post.setContent(postDTO.getContent());
            post.setLikeCount(0);
            post.setCollectCount(0);
            post.setCommentCount(0);
            post.setStatus(1); // 设置为已发布状态
            post.setIsTop(0); // 默认不置顶
            post.setCreatedAt(new Date());
            // 处理标签：将标签数组转换为逗号分隔的字符串
            if (postDTO.getTags() != null && !postDTO.getTags().isEmpty()) {
                String tagString = String.join(",", postDTO.getTags());
                post.setTag(tagString);
            }

            // 处理视频上传
            if (postDTO.getVideo() != null && !postDTO.getVideo().isEmpty()) {
                // 创建临时文件
                tempFile = File.createTempFile("video", ".mp4");
                postDTO.getVideo().transferTo(tempFile);

                // 配置 FFmpeg
                grabber = new FFmpegFrameGrabber(tempFile);
                grabber.setFormat("mp4"); // 设置格式
                grabber.setOption("analyzeduration", "2147483647"); // 分析持续时间
                grabber.setOption("probesize", "2147483647"); // 探测大小

                try {
                    grabber.start();
                    // 获取视频时长
                    double duration = grabber.getLengthInTime() / 1000000.0; // 转换为秒
                    post.setDuration(duration);

                    // 获取第一帧作为封面
                    Frame frame = grabber.grabImage();
                    if (frame != null) {
                        Java2DFrameConverter converter = new Java2DFrameConverter();
                        BufferedImage bufferedImage = converter.convert(frame);

                        if (bufferedImage != null) {
                            coverFile = File.createTempFile("cover", ".jpg");
                            ImageIO.write(bufferedImage, "jpg", coverFile);

                            // 上传视频和封面到OSS
                            String videoUrl = ossUtil.uploadFile(new FileInputStream(tempFile), "videos", "video_" + UUID.randomUUID() + ".mp4");
                            String coverUrl = ossUtil.uploadFile(new FileInputStream(coverFile), "images", "cover_" + UUID.randomUUID() + ".jpg");

                            post.setVideoUrl(videoUrl);
                            post.setCoverUrl(coverUrl);
                        }
                    }
                } finally {
                    if (grabber != null) {
                        try {
                            grabber.stop();
                            grabber.release();
                        } catch (Exception e) {
                            //log.error("关闭FFmpeg失败", e);
                        }
                    }
                }
            }
            if (postDTO.getVideo() == null && postDTO.getImages() == null) {
                return Result.fail("未上传图片");
            }
            // 处理图片上传
            List<String> imageUrls = new ArrayList<>();
            if (postDTO.getImages() != null && !postDTO.getImages().isEmpty()) {
                for (MultipartFile image : postDTO.getImages()) {
                    // 上传图片到 OSS images 目录
                    String imageUrl = ossUtil.uploadFile(image, "images");
                    imageUrls.add(imageUrl);
                }

                // 将图片 URL 列表转换为 JSON 字符串
                ObjectMapper mapper = new ObjectMapper();
                post.setImageUrls(mapper.writeValueAsString(imageUrls));

                // 如果没有视频，使用第一张图片作为封面
                if (post.getVideoUrl() == null && !imageUrls.isEmpty()) {
                    post.setCoverUrl(imageUrls.get(0));
                }
            }

            // 保存帖子
            postsService.save(post);

            return Result.success("发布成功");

        } catch (Exception e) {
            //log.error("发布失败", e);
            return Result.fail("发布失败: " + e.getMessage());
        } finally {
            // 清理临时文件
            if (tempFile != null && tempFile.exists()) {
                tempFile.delete();
            }
            if (coverFile != null && coverFile.exists()) {
                coverFile.delete();
            }
        }
    }
    /**
     * 修改帖子
     * @param id 帖子ID
     * @param postDTO 帖子数据传输对象，包含标题、内容、标签、视频和图片
     * @return 修改结果
     */
    @PutMapping("/update/{id}")
    public Result<?> updatePost(@PathVariable Integer id,
                                @ModelAttribute PostDTO postDTO) {
        File tempFile = null;
        File coverFile = null;
        FFmpegFrameGrabber grabber = null;
        try {
            // Token 验证
            Integer userId = UserContextHolder.getUserId();

            // 获取原帖子信息
            Posts post = postsService.getById(id);
            if (post == null) {
                return Result.fail("帖子不存在");
            }

            // 权限检查
            List<String> authorities = usersService.getUserAuthorities(userId);
            boolean isAdmin = authorities.stream().anyMatch(auth -> auth.startsWith("ROLE_ADMIN"));
            if (!isAdmin && !userId.equals(post.getUserId())) {
                return Result.fail("无权修改此帖子");
            }

            // 基本信息更新
            post.setTitle(postDTO.getTitle());
            post.setContent(postDTO.getContent());
            post.setUpdatedAt(new Date());

            // 处理标签
            if (postDTO.getTags() != null && !postDTO.getTags().isEmpty()) {
                String tagString = String.join(",", postDTO.getTags());
                post.setTag(tagString);
            }

            // 处理视频更新
            if (postDTO.getVideo() != null && !postDTO.getVideo().isEmpty()) {
                // 删除原视频和封面
                if (post.getVideoUrl() != null) {
                    deleteOssFile(post.getVideoUrl());
                }
                if (post.getCoverUrl() != null && post.getVideoUrl() != null) {
                    deleteOssFile(post.getCoverUrl());
                }

                // 上传新视频
                tempFile = File.createTempFile("video", ".mp4");
                postDTO.getVideo().transferTo(tempFile);

                grabber = new FFmpegFrameGrabber(tempFile);
                grabber.setFormat("mp4");
                grabber.setOption("analyzeduration", "2147483647");
                grabber.setOption("probesize", "2147483647");

                try {
                    grabber.start();
                    double duration = grabber.getLengthInTime() / 1000000.0;
                    post.setDuration(duration);

                    Frame frame = grabber.grabImage();
                    if (frame != null) {
                        Java2DFrameConverter converter = new Java2DFrameConverter();
                        BufferedImage bufferedImage = converter.convert(frame);

                        if (bufferedImage != null) {
                            coverFile = File.createTempFile("cover", ".jpg");
                            ImageIO.write(bufferedImage, "jpg", coverFile);

                            String videoUrl = ossUtil.uploadFile(new FileInputStream(tempFile),
                                    "videos", "video_" + UUID.randomUUID() + ".mp4");
                            String coverUrl = ossUtil.uploadFile(new FileInputStream(coverFile),
                                    "images", "cover_" + UUID.randomUUID() + ".jpg");

                            post.setVideoUrl(videoUrl);
                            post.setCoverUrl(coverUrl);
                        }
                    }
                } finally {
                    if (grabber != null) {
                        try {
                            grabber.stop();
                            grabber.release();
                        } catch (Exception e) {
                            // 忽略关闭异常
                        }
                    }
                }
            }

            // 处理图片更新
            if (postDTO.getImages() != null && !postDTO.getImages().isEmpty()) {
                // 删除原图片
                if (post.getImageUrls() != null) {
                    ObjectMapper mapper = new ObjectMapper();
                    List<String> oldImageUrls = mapper.readValue(post.getImageUrls(), List.class);
                    for (String oldImageUrl : oldImageUrls) {
                        deleteOssFile(oldImageUrl);
                    }
                }

                // 上传新图片
                List<String> newImageUrls = new ArrayList<>();
                for (MultipartFile image : postDTO.getImages()) {
                    String imageUrl = ossUtil.uploadFile(image, "images");
                    newImageUrls.add(imageUrl);
                }

                // 更新图片URLs
                ObjectMapper mapper = new ObjectMapper();
                post.setImageUrls(mapper.writeValueAsString(newImageUrls));

                // 如果没有视频，使用第一张图片作为封面
                if (post.getVideoUrl() == null && !newImageUrls.isEmpty()) {
                    post.setCoverUrl(newImageUrls.get(0));
                }
            }

            // 保存更新
            boolean success = postsService.updateById(post);
            if (!success) {
                return Result.fail("数据库更新失败");
            }
            return Result.success("修改成功");

        } catch (Exception e) {
            return Result.fail("修改失败: " + e.getMessage());
        } finally {
            // 清理临时文件
            if (tempFile != null && tempFile.exists()) {
                tempFile.delete();
            }
            if (coverFile != null && coverFile.exists()) {
                coverFile.delete();
            }
        }
    }

    /**
     * 删除OSS文件
     *
     * @param fileUrl 完整的OSS文件URL
     */
    private void deleteOssFile(String fileUrl) {
        try {
            // 从完整URL中提取文件路径
            String objectName = fileUrl.substring(fileUrl.indexOf("/", 8));
            ossUtil.deleteFile(objectName);
        } catch (Exception e) {
            // 记录删除失败，但不影响整体流程
            //log.error("删除OSS文件失败: " + fileUrl, e);
        }
    }

    /**
     * 删除帖子
     * @param token
     * @param id 帖子ID
     * @return 删除结果
     */
    @DeleteMapping("/delete/{id}")
    public Result<?> deleteCommentById(@RequestHeader("Authorization") String token,
                                        @PathVariable Integer id) {
        try {
            if (token == null || !token.startsWith("Bearer ")) {
                return Result.fail("未提供有效的token");
            }
            String actualToken = token.substring(7);

            // 验证并解析token
            if (!jwtUtil.validateToken(actualToken)) {
                return Result.fail("token无效或已过期");
            }

            var claims = jwtUtil.parseToken(actualToken);
            Integer userId = ((Number) claims.get("userId")).intValue();

            Posts post = postsService.getById(id);
            if (post == null) {
                return Result.fail("帖子不存在");
            }

            // 检查用户权限
            List<String> authorities = usersService.getUserAuthorities(userId);
            boolean isAdmin = authorities.stream().anyMatch(auth -> auth.startsWith("ROLE_ADMIN"));

            // 如果不是管理员且不是帖子作者，则无权删除
            if (!isAdmin && !userId.equals(post.getUserId())) {
                return Result.fail("无权删除此帖子");
            }

            postsService.removePostById(id);
            return Result.success("删除成功");
        }
        catch (Exception e) {
            return Result.fail("删除失败: " + e.getMessage());
        }
    }
    /**
     * 搜索帖子
     *
     * @param keyword 关键词
     * @param page 页码
     * @param limit 每页大小
     * @param tag 标签（可选）
     * @return 点赞结果
     */
    @GetMapping("/search")
    public Result<?> searchPosts(
            @RequestParam String keyword,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer limit,
            @RequestParam(required = false) String tag) {
        try {
            Page<PostCardVO> posts = postsService.searchPosts(keyword, page, limit, tag);
            return Result.success("搜索成功", posts); // 直接返回Page对象，它包含了总数和分页数据
        } catch (Exception e) {
            return Result.fail("搜索失败: " + e.getMessage());
        }
    }
    /**
     * 用户帖子推荐
     * @param token 用户的JWT令牌
     * @param page 页码
     * @param limit 每页大小
     * return 推荐结果
     */
    @GetMapping("/myRecommend")
    public Result<?> recommendMyPosts(
        @RequestHeader("Authorization") String token,
        @RequestParam(defaultValue = "1") Integer page,
        @RequestParam(defaultValue = "10") Integer limit) {
        try {
            if (token == null || !token.startsWith("Bearer ")) {
                return Result.fail("未提供有效的token");
            }
            String actualToken = token.substring(7);

            // 验证并解析token
            if (!jwtUtil.validateToken(actualToken)) {
                return Result.fail("token无效或已过期");
            }

            var claims = jwtUtil.parseToken(actualToken);
            Integer userId = ((Number) claims.get("userId")).intValue();

            Page<PostCardVO> postsPage = postsService.recommendSimilarPosts(userId, page, limit);
            return Result.success(postsPage);
        } catch (Exception e) {
            return Result.fail("获取推荐帖子失败: " + e.getMessage());
        }
    }

}
